home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / geomview / source.lha / Geomview / src / lib / mg / ri / mgri.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-08  |  25.4 KB  |  1,003 lines

  1. #include "mgriP.h"
  2. #include "mgrishade.h"
  3. #include <stdio.h>
  4. #include <sys/types.h>
  5. #include <stdlib.h>
  6. #import <appkit/appkit.h>
  7. #include <sys/time.h>
  8. #include <sys/resource.h>        /* For enlarging stack size */
  9.  
  10. mgcontext * mgri_ctxcreate(int a1, ...);
  11. void        mgri_ctxset( int a1, ...  );
  12. int        mgri_feature( int feature );
  13. void        mgri_ctxdelete( mgcontext *ctx );
  14. int        mgri_ctxget( int attr, void* valueptr );
  15. int        mgri_ctxselect( mgcontext *ctx );
  16. void        mgri_sync( void );
  17. void        mgri_worldbegin( void );
  18. void        mgri_worldend( void );
  19. void        mgri_reshapeviewport( void );
  20. void        mgri_identity( void );
  21. void        mgri_transform( Transform T );
  22. void        mgri_pushtransform( void );
  23. void        mgri_poptransform( void );
  24. void        mgri_gettransform( Transform T );
  25. void        mgri_settransform( Transform T );
  26. void        mgri_material( struct mgastk *mastk, int merge );
  27. int        mgri_pushappearance( void );
  28. int        mgri_popappearance( void );
  29. Appearance  *mgri_setappearance( Appearance* app, int merge );
  30. Appearance  *mgri_getappearance( void );
  31. int        mgri_setcamera( Camera* cam );
  32. mgricontext *mgri_newcontext( mgricontext *ctx );
  33.  
  34. extern void  mgri_polygon();
  35. extern void  mgri_mesh();
  36. extern void  mgri_line();
  37. extern void  mgri_polyline();
  38. extern void  mgri_polylist();
  39.  
  40. void _mgri_ctxset(int a1, va_list *alist);
  41.  
  42. extern int mgri_nxwindow(int x, int y, int xsize, int ysize,
  43.             char *name, int noborder, unsigned int *globalNum);
  44. extern void mgri_closewindow(mgricontext *thectx);
  45. extern void mgri_display();
  46. extern void mgri_getnxrect(float *f);
  47. extern void mgri_clear();
  48. extern void mgri_flush();
  49. extern RtPointer mgri_vieworigin();
  50. extern void mgri_startdebugcontext();
  51. extern void mgri_stopdebugcontext();
  52. extern void mgri_errorhandler();
  53.  
  54. WnWindow *mgriwindow(WnWindow *win);
  55.  
  56. struct mgfuncs mgrifuncs = {
  57.   MGD_RI,
  58.   mgdevice_RI,
  59.   mgri_feature,
  60.   (mgcontext *(*)())mgri_ctxcreate,
  61.   mgri_ctxdelete,
  62.   (void (*)())mgri_ctxset,
  63.   mgri_ctxget,
  64.   mgri_ctxselect,
  65.   mgri_sync,
  66.   mgri_worldbegin,
  67.   mgri_worldend,
  68.   mgri_reshapeviewport,
  69.   mgri_settransform,
  70.   mgri_gettransform,
  71.   mgri_identity,
  72.   mgri_transform,
  73.   mgri_pushtransform,
  74.   mgri_poptransform,
  75.   mgri_pushappearance,
  76.   mgri_popappearance,
  77.   mgri_setappearance,
  78.   mgri_getappearance,
  79.   mgri_setcamera,
  80.   mgri_polygon,
  81.   mgri_polylist,
  82.   mgri_mesh,
  83.   mgri_line,
  84.   mgri_polyline,
  85.   mg_quads,
  86.   mg_bezier,
  87.   };
  88.  
  89. /* for debugging simplification: */
  90. static mgricontext *MGRI;
  91.  
  92. /* our renderman<->oogl z axis flip transform */
  93. Transform cam2ri = {{1, 0,0,0}, {0,1,0,0}, {0,0,-1,0},{0,0,0,1}};
  94.  
  95. /* our QRMAN interface buffers */
  96. RtPoint *ript;        /* points */
  97. RtColor *ricolor;    /* rgb color */
  98. RtPoint *rinormal;    /* normals */
  99. int *rippi;        /* PointsPolygon polygon index array */
  100. int rippis;        /* PointsPolygon polygon index array size */
  101. int *ripvi;        /* PointsPolygon vertex index array */
  102. int ripvis;        /* PointsPolygon vertex index array size */
  103.  
  104. RtPoint *plpt;        /* verticees for buffered polylines */
  105. RtColor *plcolor;    /* colors for buffered polylines */
  106. RtPoint *plp;          /* vertices */
  107. RtColor *plc;          /* colors */
  108. int *plvca;            /* polyline vertex count array */
  109. int *plvia;            /* vertex index array */
  110.  
  111. int
  112. mgdevice_RI()
  113. {
  114.   _mgf = mgrifuncs;
  115.   if (_mgc != NULL && _mgc->devno != MGD_RI)
  116.     _mgc = NULL;
  117.  
  118.   return(0);
  119. }
  120.  
  121. /*-----------------------------------------------------------------------
  122.  * Function:    mgri_ctxcreate
  123.  * Date:    Thu Jul 18 18:55:18 1991
  124.  * Author:    mbp
  125.  * Notes:    see mg.doc for rest of spec
  126.  */
  127. mgcontext *
  128. mgri_ctxcreate(int a1, ...)
  129. {
  130.   va_list alist;
  131.   struct rlimit rl;
  132.  
  133.    /* Since we depend on alloca() for copying some OOGL data structures,
  134.     * ensure we're allowed a reasonable amount of stack space.
  135.     * NeXT default seems to be .5MB, not enough.
  136.     */
  137.   getrlimit(RLIMIT_STACK, &rl);
  138.   if(rl.rlim_cur < 24*1024*1024) {
  139.     rl.rlim_cur = 24*1024*1024;
  140.     setrlimit(RLIMIT_STACK, &rl);
  141.   }
  142.  
  143.   _mgc =
  144.     (mgcontext*)(MGRI = mgri_newcontext( OOGLNewE(mgricontext, "mgri_ctxcreate") ));
  145.  
  146.   /* Ensure some sensible default Window */
  147.   WnSet(_mgc->win, WN_XSIZE, 500, WN_YSIZE, 400, WN_END);
  148.  
  149.   va_start(alist, a1);
  150.   _mgri_ctxset(a1, &alist);
  151.   va_end(alist);
  152.   return _mgc;
  153. }
  154.  
  155. /*-----------------------------------------------------------------------
  156.  * Function:    _mgri_ctxset
  157.  * Description:    internal ctxset routine
  158.  * Args:    a1: first attribute
  159.  *        *alist: rest of attribute-value list
  160.  * Returns:    nothing
  161.  * Author:    mbp, wisdom
  162.  * Date:    Fri Sep 20 11:08:13 1991
  163.  * Notes:    mgri_ctxcreate() and mgri_ctxset() call this to actually
  164.  *        parse and interpret the attribute list.
  165.  */
  166. void
  167. _mgri_ctxset(int a1, va_list *alist)
  168. {
  169.   int attr;
  170.   char *name;
  171.   
  172.   for (attr = a1; attr != MG_END; attr = va_arg (*alist, int)) {
  173.     switch (attr) {
  174.     case MG_ApSet:
  175.       {
  176.     Appearance *ap;
  177.  
  178.     ap = _ApSet(NULL, va_arg(*alist, int), alist);
  179.     mgri_setappearance(ap, MG_MERGE);
  180.     ApDelete(ap);
  181.       }
  182.       break;
  183.     case MG_WnSet:
  184.     _WnSet( _mgc->win, va_arg(*alist, int), alist);
  185.     if(_mgc->shown) {
  186.       WnGet(_mgc->win, WN_NAME, &name);
  187.       if(_mgric->born)
  188.           if(name)
  189.           [(id)_mgric->nxwindow setTitle:name]; //wintitle(name);
  190.       }
  191.         break;
  192.     case MG_CamSet:
  193.       _CamSet( _mgc->cam, va_arg(*alist, int), alist);
  194.       break;
  195.     case MG_APPEAR:
  196.       mgsetappearance(va_arg(*alist, Appearance *), MG_SET);
  197.       break;
  198.     case MG_WINDOW:
  199.       if (_mgc->win) WnDelete(_mgc->win);
  200.       _mgc->win = va_arg(*alist, WnWindow*);
  201.       RefIncr((Ref*) (_mgc->win));
  202.       break;
  203.     case MG_CAMERA:
  204.       mgri_setcamera( va_arg(*alist, Camera*) );
  205.       break;
  206.     case MG_SETOPTIONS:
  207.       _mgc->opts |= va_arg(*alist, int);
  208.     case MG_UNSETOPTIONS:
  209.       _mgc->opts &= ~va_arg(*alist, int);
  210.       break;
  211.     case MG_SHOW:
  212.       _mgc->shown = va_arg(*alist, int);
  213.       break;
  214.     case MG_PARENT:
  215.       _mgc->parent = va_arg(*alist, mgcontext*);
  216.       break;
  217.     case MG_BACKGROUND:
  218.       _mgc->background = *va_arg(*alist, ColorA*);
  219.       break;
  220.     case MG_ZNUDGE:
  221.       _mgc->zfnudge = va_arg(*alist, double);
  222.       break;
  223.  
  224.     case MG_SPACE:
  225.     {
  226.     int space = va_arg(*alist, int);
  227.     _mgc->space = space; 
  228.     if(! ((space & TM_EUCLIDEAN) || (space & TM_HYPERBOLIC) ||
  229.          (space & TM_SPHERICAL)))
  230.     fprintf(stderr, "_mgri_ctxset: Illegal space value %1d\n", space);
  231.    }
  232.    break;
  233.  
  234.     case MG_SHADER: mgri_setshader( va_arg(*alist, mgshadefunc) ); break;
  235.     case MG_SHADERDATA: _mgc->astk->shaderdata = va_arg(*alist, void*); break;
  236.     case MG_NDINFO: _mgc->NDinfo = va_arg(*alist, void *); break;
  237.     case MG_NDMAP:  _mgc->NDmap = va_arg(*alist, mgmapfunc); break;
  238.  
  239.     /* NeXT specific */
  240.     case MG_NXWINDOW:
  241.         _mgric->nxwindow = va_arg(*alist, char *);
  242.     break;    
  243.     case MG_NXVIEW:
  244.         _mgric->nxview = va_arg(*alist, char *);
  245.     break;
  246.     case MG_RICALLBACK:
  247.         _mgric->callback = va_arg(*alist, void *);
  248.     break;
  249.     case MG_RISTANDALONE:
  250.         _mgric->standalone = va_arg(*alist, int);
  251.     break;
  252.     default:
  253.         OOGLError (0, "_mgri_ctxset: undefined option: %d\n", attr);
  254.         return;
  255.         break;
  256.     }
  257.   }
  258.  
  259.   if (_mgc->shown && !_mgric->born) {
  260.  
  261.     /* open the window */
  262.     mgriwindow(_mgc->win);
  263.  
  264.     /* rib state is *not* in accordance with appearance state:
  265.        don't set the appearance until worldbegin time */
  266.  
  267.   }
  268. }
  269.  
  270.  
  271. /*-----------------------------------------------------------------------
  272.  * Function:    mgri_ctxget
  273.  * Description:    get a context attribute value
  274.  * Args:    attr: the attribute to get
  275.  *        value: place to write attr's value
  276.  * Returns:    1 for success; -1 if attr is invalid
  277.  * Author:    mbp, wisdom
  278.  * Date:    Fri Sep 20 11:50:25 1991
  279.  * Notes:
  280.  */
  281. int
  282. mgri_ctxget(int attr, void* value)
  283. {
  284. #define VALUE(type) ((type*)value)
  285.  
  286.   switch (attr) {
  287.  
  288.   /* Attributes common to all MG contexts: */
  289.   case MG_APPEAR:
  290.     *VALUE(Appearance*) = &(_mgc->astk->ap);
  291.     break;
  292.   case MG_CAMERA:
  293.     *VALUE(Camera*) = _mgc->cam;
  294.     break;
  295.   case  MG_WINDOW:
  296.     if(_mgric->born) {
  297.       WnPosition wp;
  298.       float theRect[4]; /* origin.x, origin.y, size.width, size.height */
  299.  
  300.       mgri_getnxrect(theRect);
  301.       
  302.       wp.xmin = theRect[0];
  303.       wp.xmax = theRect[0]+theRect[2]-1;
  304.       wp.ymin = theRect[1];
  305.       wp.ymax = theRect[1]+theRect[3]-1;
  306.       WnSet(_mgc->win, WN_CURPOS, &wp, WN_END);
  307.     }
  308.     *VALUE(WnWindow*) = _mgc->win;
  309.     break;
  310.   case MG_PARENT:
  311.     *VALUE(mgcontext*) = _mgc->parent;
  312.     break;
  313.   case MG_SETOPTIONS:
  314.   case MG_UNSETOPTIONS:
  315.     *VALUE(int) = _mgc->opts;
  316.     break;
  317.   case MG_BACKGROUND:
  318.     *VALUE(ColorA) = _mgc->background;
  319.     break;
  320.   case MG_SPACE:
  321.     *VALUE(int) = _mgc->space;
  322.     break;
  323.   case MG_ZNUDGE:
  324.     *VALUE(float) = _mgc->zfnudge;
  325.     break;
  326.   case MG_SHADER: *VALUE(mgshadefunc) = _mgc->astk->shader; break;
  327.   case MG_SHADERDATA: *VALUE(void *) = _mgc->astk->shaderdata; break;
  328.   case MG_NDINFO: *VALUE(void *) = _mgc->NDinfo; break;
  329.   case MG_NDMAP: *VALUE(mgmapfunc) = _mgc->NDmap; break;
  330.     
  331.   /* Attributes specific to RI contexts: */
  332.   case MG_RIWINID:
  333.     *VALUE(int) = _mgric->win;
  334.     break;
  335.     
  336.   /* specific to NeXT */
  337.   case MG_NXWINDOW:
  338.      *VALUE(char *) = _mgric->nxwindow;
  339.      break;
  340.   case MG_NXVIEW:
  341.      *VALUE(char *) = _mgric->nxview;
  342.      break;
  343.   case MG_RICALLBACK:
  344.      *VALUE(void *) = _mgric->callback;
  345.      break;
  346.   case MG_RISTANDALONE:
  347.      *VALUE(int) = _mgric->standalone;
  348.      break;
  349.   default:
  350.     OOGLError (0, "mgri_ctxget: undefined option: %d\n", attr);
  351.     return -1;
  352.  
  353.   }
  354.   return 1;
  355.  
  356. #undef VALUE
  357. }
  358.  
  359. /*-----------------------------------------------------------------------
  360.  * Function:    mgriwindow
  361.  * Description:    create an RI window
  362.  * Args:    *win: the WnWindow structure to realize
  363.  * Returns:    win if success, NULL if not
  364.  * Author:    wisdom, gunn
  365.  * Date:    Thu May 21 15:04:42 CDT 1992
  366.  * Notes:    makes the RI calls necessary to create an RI window
  367.  *          corresponding to *win.
  368.  */
  369. WnWindow *
  370. mgriwindow(WnWindow *win)
  371. {
  372.   WnPosition pos;
  373.   int xsize, ysize, flag, reconstrain;
  374.   char *name;
  375.   char gver[80];
  376.   double pxloc, pyloc, pxsize, pysize;
  377.   int noborder=0;
  378.   unsigned int globalNum;
  379.    
  380.     /* interpret window ...*/
  381.         
  382.     if(WnGet(win, WN_PREFPOS, (void*)&pos) == 1){
  383.     pxloc = pos.xmin;
  384.     pyloc = pos.ymin;
  385.     pxsize = pos.xmax - pos.xmin;
  386.     pysize = pos.ymax - pos.ymin;
  387.     } else if ((WnGet(win, WN_XSIZE, (void*)&xsize) == 1)
  388.     && (WnGet(win, WN_YSIZE, (void*)&ysize) == 1) ) {
  389.     pxsize = xsize;
  390.     pysize = ysize;
  391.     }
  392.     
  393.     WnGet(win, WN_NOBORDER, &flag);
  394.     if (flag) noborder=1;
  395.     
  396.     WnGet(win, WN_NAME, &name);
  397.     
  398.     mgri_nxwindow(pxloc, pyloc, pxsize, pysize, name, noborder, &globalNum);
  399.     
  400.     /* creat the renderman context */
  401.     _mgric->qrmContext = RiBegin(RI_NULL, RI_NULL);
  402.     RiHider(RI_HIDDEN,RI_NULL);
  403.     RiErrorHandler((RtFunc)mgri_errorhandler);
  404.     _mgric->windowresource = RiResource("Generic", RI_IMAGE,
  405.         RI_WINDOWID, (RtPointer)&globalNum, RI_NULL);
  406.     
  407.     _mgric->born = 1;
  408.     return(win);
  409. }
  410.  
  411. /*-----------------------------------------------------------------------
  412.  * Function:    mgri_ctxset
  413.  * Description:    set some context attributes
  414.  * Args:    a1, ...: list of attribute-value pairs
  415.  * Returns:    nothing
  416.  * Author:    mbp
  417.  * Date:    Fri Sep 20 12:00:18 1991
  418.  */
  419. void mgri_ctxset( int a1, ...  )
  420. {
  421.   va_list alist;
  422.  
  423.   va_start( alist, a1 );
  424.   _mgri_ctxset(a1, &alist);
  425.   va_end(alist);
  426. }
  427.  
  428.  
  429. /*-----------------------------------------------------------------------
  430.  * Function:    mgri_feature
  431.  * Description:    report whether the GL device has a particular feature
  432.  * Args:    feature: the feature to report on
  433.  * Returns:    an int giving info about feature
  434.  * Author:    mbp
  435.  * Date:    Fri Sep 20 12:00:58 1991
  436.  * Notes:    -1 means the feature is not present.
  437.  *
  438.  *        NO FEATURES SUPPORTED YET.  ALWAYS RETURNS -1.
  439.  */
  440. int mgri_feature( int feature )
  441. {
  442.   return(-1);
  443. }
  444.  
  445. /*-----------------------------------------------------------------------
  446.  * Function:    mgri_ctxdelete
  447.  * Description:    delete a GL context
  448.  * Args:    *ctx: context to delete
  449.  * Returns:    nothing
  450.  * Author:    slevy
  451.  * Date:    Tue Nov 12 10:29:04 CST 1991
  452.  * Notes:    Deleting the current context leaves the current-context
  453.  *        pointer set to NULL.
  454.  */
  455. void mgri_ctxdelete( mgcontext *ctx )
  456. {
  457.   if(ctx->devno != MGD_RI) {
  458.     mgcontext *was = _mgc;
  459.     mgctxselect(ctx);
  460.     mgctxdelete(ctx);
  461.     if(was != ctx)
  462.     mgctxselect(was);
  463.   } else {
  464.     if(((mgricontext *)ctx)->born) {
  465.     mgricontext *current = _mgric;
  466.     RiContext(((mgricontext *)ctx)->qrmContext, RI_NULL);
  467.     RiEnd();
  468.     /* no context active now, choose what was active if we can */
  469.     if(current!=((mgricontext *)ctx))
  470.         RiContext(current->qrmContext, RI_NULL);
  471.     mgri_closewindow((mgricontext *)ctx);
  472.     }
  473.     mg_ctxdelete(ctx);
  474.     if(ctx == _mgc)
  475.     _mgc = NULL;
  476.   }
  477. }
  478.  
  479. /*-----------------------------------------------------------------------
  480.  * Function:    mgri_ctxselect
  481.  * Description:    select an RI context --- make it current
  482.  * Args:    *ctx: the context to become current
  483.  * Returns:    0
  484.  * Author:    mbp, wisdom
  485.  * Date:    Fri Sep 20 12:04:41 1991
  486.  */
  487. int
  488. mgri_ctxselect( mgcontext *ctx )
  489. {
  490.   if(ctx == NULL || ctx->devno != MGD_RI) {
  491.     return mg_ctxselect(ctx);
  492.   }
  493.  
  494.   _mgc = ctx;
  495.   MGRI = (mgricontext *)ctx;
  496.  
  497.   if(_mgric->born)
  498.      RiContext(_mgric->qrmContext,RI_NULL);
  499.  
  500.   return(0);
  501. }
  502.  
  503. /*-----------------------------------------------------------------------
  504.  * Function:    mgri_sync
  505.  * Description:    flush buffered commands
  506.  * Returns:    nothing
  507.  * Author:    wisdom
  508.  * Date:    Wed May 13 14:34:02 CDT 1992
  509.  * Notes:
  510.  */
  511. void
  512. mgri_sync( void )
  513. {
  514.     /* qrman docs say RI_WAIT performs a flush, but net reports*/
  515.     /* indicate that this is not the case, so we flush before  */
  516.     /* we wait. this may not be a necessary for NS3.1 or higher*/
  517.  
  518.     RiSynchronize(RI_FLUSH);
  519.     RiSynchronize(RI_WAIT);
  520.  
  521.     mgri_flush();
  522. }
  523.  
  524. /*-----------------------------------------------------------------------
  525.  * Function:    mgri_worldbegin
  526.  * Description:    prepare to draw a frame
  527.  * Returns:    nothing
  528.  * Author:    gunn, wisdom
  529.  * Date:    Sat Mar  7 16:28:35 GMT-0600 1992
  530.  */
  531. void
  532. mgri_worldbegin( void )
  533. {
  534.   int persp;
  535.   RtFloat fov, aspect, near, far;
  536.   WnWindow *win;
  537.   WnPosition wp;
  538.   int xsize, ysize;
  539.   Transform T;
  540.   
  541.   static Transform *O2SP, *W2SP;    /* to ease gdb'ing */
  542.  
  543.   /* NOTE 1: Regarding cam2ri transform; in mgrib, we use an identity matrix
  544.    * with a -1 value in the z position to mirror the z axis. QuickRenderman,
  545.    * however, considers this matrix as non isometric (an error). Therefore, we
  546.    * also mirror the y axis (-1 in y pos) to retain the isometric property.
  547.    * reversing the y components of RiScreenWindow from -1,0,1.0 to 1.0,-1.0
  548.    * effectively mirrors that change back, and QRM is happy. sw7/92
  549.    */
  550.    
  551.    /* debug, if necessary */
  552.    if(_mgric->debug) {
  553.        mgri_startdebugcontext();
  554.    }
  555.     /* Interpret Options...(none exist now) */
  556.  
  557.     /* Interpret Camera ...*/
  558.     
  559.     /* the halfyfield is so confusing that I'm going to ignore it and use fov*/
  560.     /* (gunn) */
  561.     CamGet( _mgc->cam, CAM_ASPECT, &aspect);
  562.     
  563.     /* this may break it */
  564.     WnGet(_mgc->win, WN_CURPOS, &wp);
  565.     xsize = wp.xmax - wp.xmin + 1;
  566.     ysize = wp.ymax - wp.ymin + 1;
  567.  
  568.     CamGet( _mgc->cam, CAM_NEAR, &near);
  569.     CamGet( _mgc->cam, CAM_FAR, &far);
  570.     
  571.     RiClipping(near, far);
  572.  
  573.     if(_mgric->debug)
  574.     RiDisplay(_mgric->debugResource, RI_FILE, RI_RGBA,RI_NULL);
  575.     else
  576.     RiDisplay(_mgric->windowresource, RI_FRAMEBUFFER, RI_RGBAZ,
  577.         RI_ORIGIN, (RtPointer)(_mgric->mgvorigin), RI_NULL);
  578.  
  579.     RiFrameBegin(1);
  580.  
  581.     RiFormat(xsize,ysize,1.0);
  582.  
  583.     RiScreenWindow(-aspect, aspect, -1.0, 1.0);
  584.         
  585.     CamGet( _mgc->cam, CAM_PERSPECTIVE, &persp);
  586.     CamGet( _mgc->cam, CAM_FOV, &fov);
  587.     if(persp) {
  588.     RiProjection("perspective", "fov", &fov, RI_NULL);
  589.     } else {
  590.         RiProjection("orthographic",RI_NULL);
  591.     }
  592.         
  593.     RiTransform(cam2ri); //acts as our initial (twisted) identity matrix
  594.  
  595.     CamGet(_mgc->cam, CAM_W2C, _mgc->W2C);
  596.     CamGet(_mgc->cam, CAM_C2W, _mgc->C2W);
  597.     _mgric->hascpos = _mgc->xstk->hasinv = 0;
  598.     
  599.     RiConcatTransform(_mgc->W2C);
  600.  
  601.     /* RiWorldBegin...*/
  602.     mgri_clear();
  603.     RiWorldBegin();
  604.  
  605.     /* bring ri state into accordance with appearance state */
  606.     {
  607.       Appearance *ap = ApCopy( &(_mgc->astk->ap), NULL );
  608.       mgri_setappearance( ap, MG_SET );
  609.       ApDelete(ap);
  610.     }
  611.  
  612.     /* Build camera->screen matrix */
  613.  
  614.     CamView(_mgc->cam, _mgric->W2S);    /* world to {-1 .. +1} cube */
  615.     TmTranslate(T, 1.0, 1.0, 0);
  616.     TmConcat(_mgric->W2S,T, _mgric->W2S); /* world to {0..2, 0..2, -1..+1} */
  617.  
  618.     mgri_ctxget(MG_WINDOW, &win);        /* Gets size of drawing area */
  619.     WnGet(_mgc->win, WN_XSIZE, &xsize);
  620.     WnGet(_mgc->win, WN_YSIZE, &ysize);
  621.  
  622.  
  623.     TmScale(T, (double)xsize*.5, (double)ysize*.5, 1.0);
  624.     TmConcat(_mgric->W2S,T, _mgric->W2S);     /* world to window */
  625.  
  626.     TmCopy(_mgric->W2S, _mgric->O2S);    /* initially world == object space */
  627.  
  628. }
  629.  
  630. /*-----------------------------------------------------------------------
  631.  * Function:    mgri_worldend
  632.  * Description:    finish drawing a frame
  633.  * Returns:    nothing
  634.  * Author:    wisdom
  635.  * Date:    Sat Mar  7 14:47:40 GMT-0600 1992
  636.  */
  637. void
  638. mgri_worldend( void )
  639. {
  640.     /* check for any remaining buffered polylines */
  641.     if(_mgric->plni) mgri_plflush();
  642.  
  643.     RiWorldEnd();
  644.     RiFrameEnd();
  645.     mgri_sync();
  646.  
  647.     /* debugging */
  648.     if(_mgric->debug) mgri_stopdebugcontext();
  649.         
  650.     /* if the main program doesn't use the appkit (standalone=1), then
  651.      * any events are processed here. if events must be processed but mg
  652.      * isn't being called to update the window, mgri_processevents() can be
  653.      * called directly.
  654.      */
  655.  
  656.     /* if necessary, process events */
  657.     if(MGRI->standalone) mgri_processevents();
  658.  
  659. }
  660.  
  661. /*-----------------------------------------------------------------------
  662.  * Function:    mgri_reshapeviewport
  663.  * Description:    adjust to a new window size
  664.  * Returns:    nothing
  665.  * Author:    mbp
  666.  * Date:    Fri Sep 20 12:08:30 1991
  667.  * Notes:
  668.  */
  669. void
  670. mgri_reshapeviewport( void )
  671. {
  672.     WnWindow *win;
  673.     WnPosition wp;
  674.     int xsize, ysize;
  675.  
  676.     mgri_ctxget(MG_WINDOW, &win);    /* Get window; force it to ask
  677.                      * NeXTStep how big the window is
  678.                      */
  679.     WnGet(win, WN_CURPOS, &wp);
  680.     xsize = wp.xmax - wp.xmin + 1;
  681.     ysize = wp.ymax - wp.ymin + 1;
  682.  
  683.     CamSet(_mgc->cam, CAM_ASPECT, (double)xsize/(double)ysize, CAM_END);
  684.  
  685. }
  686.  
  687. /*-----------------------------------------------------------------------
  688.  * Function:    mgri_identity
  689.  * Description:    set the current object xform to identity
  690.  * Returns:    nothing
  691.  * Author:    wisdom
  692.  * Date:    Tue Sep 15 14:24:24 CDT 1992
  693.  * Notes:
  694.  *
  695.  */
  696. void
  697. mgri_identity( void )
  698. {
  699.     if(_mgric->plni) mgri_plflush();
  700.     RiIdentity();
  701.     mg_identity();
  702. }
  703.  
  704. /*-----------------------------------------------------------------------
  705.  * Function:    mgri_transform
  706.  * Description:    premultiply the object xform by T
  707.  * Args:    T
  708.  * Returns:    nothing
  709.  * Author:    wisdom
  710.  * Date:    Tue Sep 15 14:24:24 CDT 1992
  711.  * Notes:    
  712.  *
  713.  */
  714. void
  715. mgri_transform( Transform T )
  716. {
  717.     if(_mgric->plni) mgri_plflush();
  718.     mg_transform(T);
  719.     RiTransform(_mgc->xstk->T);
  720.      
  721.      _mgric->hascpos = _mgc->xstk->hasinv = 0;
  722.  
  723. }
  724.  
  725. /*-----------------------------------------------------------------------
  726.  * Function:    mgri_pushtransform
  727.  * Description:    push the object xform stack
  728.  * Returns:    nothing
  729.  * Author:    wisdom
  730.  * Date:    Tue Sep 15 14:24:24 CDT 1992
  731.  * Notes:    
  732.  *
  733.  */
  734. void
  735. mgri_pushtransform( void )
  736. {
  737.     if(_mgric->plni) mgri_plflush();
  738.     RiTransformBegin();
  739.     mg_pushtransform();
  740. }
  741.  
  742. /*-----------------------------------------------------------------------
  743.  * Function:    mgri_popransform
  744.  * Description:    pop the object xform stack
  745.  * Returns:    nothing
  746.  * Author:    wisdom
  747.  * Date:    Tue Sep 15 14:24:24 CDT 1992
  748.  * Notes:    
  749.  *
  750.  */
  751. void
  752. mgri_poptransform( void )
  753. {
  754.     if(_mgric->plni) mgri_plflush();
  755.     RiTransformEnd();
  756.     mg_poptransform();
  757.     _mgric->hascpos = 0;
  758. }
  759.  
  760. /*-----------------------------------------------------------------------
  761.  * Function:    mgri_gettransform
  762.  * Description:    get the current object xform
  763.  * Args:    T: place to write the current object xform
  764.  * Returns:    nothing
  765.  * Author:    wisdom
  766.  * Date:    Tue Sep 15 17:16:35 CDT 1992
  767.  * Notes:    
  768.  *
  769.  */
  770. void
  771. mgri_gettransform( Transform T )
  772. {
  773.     TmCopy(_mgc->xstk->T, T);
  774. }
  775.  
  776. /*-----------------------------------------------------------------------
  777.  * Function:    mgri_settransform
  778.  * Description:    set the current object xform to T
  779.  * Args:    T
  780.  * Returns:    nothing
  781.  * Author:    wisdom
  782.  * Date:    Tue Sep 15 17:06:51 CDT 1992
  783.  * Notes:    
  784.  *
  785.  */
  786. void
  787. mgri_settransform( Transform T )
  788. {
  789.     if(_mgric->plni) mgri_plflush();
  790.     RiTransform(T);
  791.     mg_settransform( T );
  792.  
  793.     _mgric->hascpos = _mgc->xstk->hasinv = 0;
  794.     
  795. }
  796.  
  797. /*-----------------------------------------------------------------------
  798.  * Function:    mgri_pushappearance
  799.  * Description:    push the MG context appearance stack
  800.  * Returns:    nothing
  801.  * Author:    wisdom
  802.  * Date:    Fri Sep 20 12:54:19 1991
  803.  */
  804. int
  805. mgri_pushappearance( void )
  806. {
  807.   mg_pushappearance();
  808.   RiAttributeBegin();
  809. }
  810.  
  811. /*-----------------------------------------------------------------------
  812.  * Function:    mgri_popappearance
  813.  * Description:    pop the MG context appearance stack
  814.  * Returns:    nothing
  815.  * Author:    munzner? wisdom?
  816.  * Date:    ?
  817.  * Note:
  818.  */
  819. int
  820. mgri_popappearance( void )
  821. {
  822.   register struct mgastk *mastk = _mgc->astk;
  823.   register struct mgastk *mastk_next;
  824.  
  825.   if (! (mastk_next=mastk->next)) {
  826.     OOGLError(0, "mgri_popappearance: appearance stack has only 1 entry.\n");
  827.     return;
  828.   }
  829.  
  830.   RiAttributeEnd();
  831.   mg_popappearance();
  832.  
  833.  
  834. }
  835.  
  836. /*-----------------------------------------------------------------------
  837.  * Function:    mgri_setappearance
  838.  * Author:    munzner, mbp
  839.  * Date:    Wed Aug  7 01:08:07 1991
  840.  * Notes:
  841.  */
  842. Appearance *
  843. mgri_setappearance( Appearance* ap, int mergeflag )
  844. {
  845.   int changed, mat_changed, lng_changed;
  846.   struct mgastk *mastk = _mgc->astk;
  847.   Appearance *ma;
  848.   static float nullarray[] = { 0.0 };
  849.  
  850.   ma = &(mastk->ap);
  851.  
  852.   /* Decide what changes */
  853.   if (mergeflag == MG_MERGE) {
  854.     changed = ap->valid & ~(ma->override &~ ap->override);
  855.     mat_changed =
  856.       ap->mat ? ap->mat->valid & ~(ma->mat->override &~ ap->mat->override) : 0;
  857.     lng_changed =
  858.       ap->lighting ? ap->lighting->valid &
  859.         ~(ma->lighting->override &~ ap->lighting->override) : 0;
  860.   }
  861.   else {
  862.     changed = ap->valid;
  863.     mat_changed = ap->mat ? ap->mat->valid : 0;
  864.     lng_changed = ap->lighting ? ap->lighting->valid : 0;
  865.   }
  866.  
  867.   mg_setappearance( ap, mergeflag );
  868.  
  869.   /* here is where everything gets set (sort of) */
  870.  
  871.   if(_mgric->born) {
  872.     mgri_appearance( mastk, changed);
  873.  
  874.     /* interpret lights ... */
  875.     mgri_lighting(_mgc->astk, lng_changed);
  876.  
  877.     if (ap->mat) mgri_material( mastk, mat_changed );
  878.   }
  879.  
  880. }
  881.  
  882.  
  883. /*-----------------------------------------------------------------------
  884.  * Function:    mgri_getappearance
  885.  * Description:    return a ptr to current appearance
  886.  * Returns:    ptr to current appearance
  887.  * Author:    mbp
  888.  * Date:    Fri Sep 20 13:00:41 1991
  889.  * Notes:    Applications should not modify the returned appearance
  890.  *        in any way.
  891.  */
  892. Appearance *
  893. mgri_getappearance()
  894. {
  895.     return &(_mgc->astk->ap);
  896. }
  897.  
  898. /*-----------------------------------------------------------------------
  899.  * Function:    mgri_setcamera
  900.  * Description:    set the context's camera (pointer)
  901.  * Args:    *cam: the camera to use
  902.  * Returns:    nothing
  903.  * Author:    mbp
  904.  * Date:    Fri Sep 20 13:07:31 1991
  905.  * Notes:    The context stores a pointer to the camera, not a copy
  906.  *        of it.
  907.  */
  908. int
  909. mgri_setcamera( Camera* cam )
  910. {
  911.   if (_mgc->cam) CamDelete(_mgc->cam);
  912.   _mgc->cam = cam;
  913.   RefIncr((Ref*) cam);
  914. }
  915.  
  916. /*-----------------------------------------------------------------------
  917.  * Function:    mgri_newcontext
  918.  * Description:    initialize a new mgricontext structure
  919.  * Args:    *ctx: the struct to initialize
  920.  * Returns:    ctx
  921.  * Author:    wisdom (mbp)
  922.  * Date:    Fri Nov  5 14:29:45 CST 1993
  923.  */
  924. mgricontext *
  925. mgri_newcontext( mgricontext *ctx )
  926. {
  927.   static int first = 1; /* mgri must do housekeeping first time around */
  928.             /* does this belong in mgdevice_RI() ?         */
  929.   
  930.   mg_newcontext(&(ctx->mgctx));
  931.   ctx->mgctx.devfuncs = &mgrifuncs;
  932.   ctx->mgctx.devno = MGD_RI;
  933.   ctx->mgctx.astk->ap_seq = 1;
  934.   ctx->mgctx.astk->mat_seq = 1;
  935.   ctx->mgctx.astk->light_seq = 1;
  936.   ctx->born = 0;
  937.   ctx->dying = 0;
  938.   ctx->drawsfaces = 0;
  939.   ctx->nxwindow = 0;
  940.   ctx->nxview = 0;
  941.   ctx->callback = NULL;
  942.   TmIdentity( ctx->W2C );
  943.   TmIdentity( ctx->C2W );
  944.  
  945. #ifdef NS_3_X_FAST
  946.   ctx->polymode = MGRI_POINTSPOLYGONS;
  947.   ctx->fflushlimit = ctx->lflushlimit = 1e4;
  948.   ctx->plbuffsize = 1e4;
  949. #endif
  950.   
  951. #ifdef NS_3_0_SLOW
  952.   ctx->polymode = MGRI_DEVIDEDPOLYLIST;
  953.   ctx->plbuffsize = 400;
  954. #endif
  955.  
  956.   if(first) {
  957.     /* perform general mgri housekeeping for initial context */
  958.  
  959.     first = 0;
  960.   
  961.     /* setup the scratch buffers */
  962.     ript = (RtPoint *)malloc(SCRATCHSIZE*sizeof(RtPoint));
  963.     ricolor = (RtColor *)malloc(SCRATCHSIZE*sizeof(RtColor));
  964.     rinormal = (RtPoint *)malloc(SCRATCHSIZE*sizeof(RtPoint));
  965.     rippis = 1000; /* start at 1000 polygons limit - will adjust if needed */
  966.     rippi = (int *)malloc(rippis*sizeof(int));
  967.     ripvis = rippis*6;
  968.     ripvi = (int *)malloc(ripvis*sizeof(int));
  969.  
  970.     plp = (RtPoint *)malloc((ctx->plbuffsize+100)*sizeof(RtPoint));
  971.     plc = (RtColor *)malloc((ctx->plbuffsize+100)*sizeof(RtColor));
  972.     plvca = (int *)malloc(ctx->plbuffsize*sizeof(int));
  973.     plvia = (int *)malloc((ctx->plbuffsize+100)*sizeof(int));
  974.   }
  975.   
  976.   ctx->debug = 0;
  977.   ctx->debugContext = 0;
  978.   ctx->plni = 0;
  979.   ctx->plvi = 0;
  980.   
  981.   return ctx;
  982. }
  983.  
  984. /*-----------------------------------------------------------------------
  985.  * Function:    mgri_findctx
  986.  * Description: Given an nxwindow , returns the associated mg context.
  987.  * Returns:    mgcontext * for success, NULL if none exists.
  988.  * Author:    wisdom
  989.  * Date:    Wed May 20 19:22:53 CDT 1992
  990.  * Notes:    This is a public routine.
  991.  */
  992. mgcontext *
  993. mgri_findctx(char *winid)
  994. {
  995.   register struct mgcontext *mgc;
  996.  
  997.   for(mgc = _mgclist; mgc != NULL; mgc = mgc->next) {
  998.     if(mgc->devno == MGD_RI && ((mgricontext *)mgc)->nxwindow == winid)
  999.     return mgc;
  1000.   }
  1001.   return NULL;
  1002. }
  1003.